#include "Trans3.h"

Trans3_T* Trans3_t;

//************************************
// Method:    	CALCU_SAMA					//< SAMA运算函数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	bool						//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	float dt					//< 运算周期
// Parameter: 	bool * DI					//< 数字量输入值数组指针
// Parameter: 	bool * DO					//< 数字量输出值数组指针
// Parameter: 	bool * AI					//< 模拟量输入值数组指针
// Parameter: 	bool * AO					//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(Trans3)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
#define min(x, y) {\
		typeof(x) _min1 = (x);\
		typeof(y) _min2 = (y);\
		(void) (&_min1 == &_min2);\
		_min1 < _min2 ? _min1 : _min2;}

#define max(x, y) {\
		typeof(x) _max1 = (x);\
		typeof(y) _max2 = (y);\
		(void) (&_max1 == &_max2);\
		_max1 > _max2 ? _max1 : _max2; }

#define PV1_Work {\
		if (Work_Mode == Trans3_PV1_Out)	/*工作在模式PV1*/\
		{\
			if (AIfLink[0][0] == false)\
				Work_Mode = Trans3_AUTO;\
			else\
			{\
				AO_Value = PV1_Value;\
				Alert_Sig = false;\
				MRE = Trans3_Hold;\
			}\
		}\
	}

#define PV2_Work {\
		if (Work_Mode == Trans3_PV2_Out)	/*工作在模式PV2*/\
		{\
			if (AIfLink[1][0] == false)\
				Work_Mode = Trans3_AUTO;\
			else\
			{\
				AO_Value = PV2_Value;\
				Alert_Sig = false;\
				MRE = Trans3_Hold;\
			}\
		}\
	}

#define PV3_Work {\
		if (Work_Mode == Trans3_PV3_Out)	/*工作在模式PV2*/\
		{\
			if (AIfLink[2][0] == false)\
				Work_Mode = Trans3_AUTO;\
			else\
			{\
				AO_Value = PV3_Value;\
				Alert_Sig = false;\
				MRE = Trans3_Hold;\
			}\
		}\
	}

#define AO1_Out(Value1,Value2) {\
		if(Out_Mode==Trans3_Average)  AO_Value=(Value1+Value2)/2;\
		else if(Out_Mode==Trans3_Max) AO_Value=(max(Value1,Value2));/*duan max务必用()括起来*/\
		else if(Out_Mode==Trans3_Min) AO_Value=(min(Value1,Value2));\
		else if(Out_Mode==Trans3_Middle) AO_Value=(Value1+Value2)/2;\
		Alert_Sig = true;\
		MRE = Trans3_Hold;\
}

#define AOSafe_Out {\
		AO_Value = Safe_OutValue;/* duan 按照文档编写，与明华不同*/\						
		Alert_Sig = true;\
		MRE = Trans3_Change_MAN;\
}

#define AOBeyond_Out(Value1,Value2)  {\
		if(Out_Mode==Trans3_Average)  AO_Value=(Value1+Value2)/2;\
		else if(Out_Mode==Trans3_Max) AO_Value=(max(Value1,Value2));/*duan max务必用()括起来*/\
		else if(Out_Mode==Trans3_Min) AO_Value=(min(Value1,Value2));\
		Alert_Sig = true;\
		MRE = Trans3_Hold;\
}

#define AO2_Out(Value1){\
		AO_Value=Value1;\
		Alert_Sig=true;\
		MRE = Trans3_Change_MAN;\
}
	/****************变量定义区开始**************/
	
	int i;
	int j;
	float Value1;
	float Value2;
	float tmp_float = 0;
	float tmp_in[3];
	Trans3_BeyondRan_Sta Range_12 = Trans3_Normal;
	Trans3_BeyondRan_Sta Range_13 = Trans3_Normal;
	Trans3_BeyondRan_Sta Range_23 = Trans3_Normal;

	/*<<<<<定义输入变量>>>>>*/
	float PV1_Value;
	float PV2_Value;
	float PV3_Value;

	/*<<<<<定义输出变量>>>>>*/
	float AO_Value = 0;
	bool Alert_Sig;
	Trans3_ChangeAM MRE;

	/*<<<<<定义参数变量>>>>>*/
	Trans3_WorkMode Work_Mode;
	Trans3_OutMode Out_Mode;

	float Alert_Range;
	float Alert_Dead;
	float Safe_OutValue;
	
	/*<<<<<定义中间变量>>>>>*/
	bool* AIfLink[3];					//< 记录模拟量输入的有效测点

	/****************变量定义区结束**************/

	NAME(Trans3)* Obj = (NAME(Trans3)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	PV1_Value = AI[0];
	PV2_Value = AI[1];
	PV3_Value = AI[2];

	/*<<<<<参数变量赋值>>>>>*/
	Work_Mode = Obj->Par.Work_Mode;
	Out_Mode = Obj->Par.Out_Mode;
	Alert_Range = Obj->Par.Alert_Range;
	Alert_Dead = Obj->Par.Alert_Dead;
	Safe_OutValue = Obj->Par.Safe_OutValue;

	/*<<<<<中间变量赋值>>>>>*/
	for (i = 0; i < 3; i++)
		AIfLink[i] = &(Obj->Sta.AIfLink[i]);

	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/

	if (AIfLink[0][0] == true)										//< duan0828
	{
		if (*(Obj->Base.In.AI_Pin_QualityInfo[0]) == true)
			AIfLink[0][0] = false;
	}

	if (AIfLink[1][0] == true)
	{
		if (*(Obj->Base.In.AI_Pin_QualityInfo[1]) == true)
			AIfLink[1][0] = false;
	}

	if (AIfLink[2][0] == true)
	{
		if (*(Obj->Base.In.AI_Pin_QualityInfo[2]) == true)
			AIfLink[1][0] = false;
	}


	tmp_in[0] = PV1_Value;
	tmp_in[1] = PV2_Value;
	tmp_in[2] = PV3_Value;

	for (i = 0; i < 3; i++)												//< 数组中元素由小到大排序
	{
		for (j = 0; j < 2 - i; j++)
		{
			if (tmp_in[j] > tmp_in[j + 1])
			{
				tmp_float = tmp_in[j];
				tmp_in[j] = tmp_in[j + 1];
				tmp_in[j + 1] = tmp_float;
			}
		}
	}

	PV1_Work;										//< 工作方式为PV1
	PV2_Work;										//< 工作方式为PV2
	PV3_Work;										//< 工作方式为PV3

	if (Work_Mode == Trans3_AUTO)					//< 工作方式为自动
	{
		if (fabs(PV1_Value - PV2_Value) > Alert_Range + Alert_Dead)  Range_12 = Trans3_Beyond;
		if (fabs(PV1_Value - PV3_Value) > Alert_Range + Alert_Dead)  Range_13 = Trans3_Beyond;
		if (fabs(PV2_Value - PV3_Value) > Alert_Range + Alert_Dead)  Range_23= Trans3_Beyond;

		if (AIfLink[0][0] == false && AIfLink[1][0] == true && AIfLink[2][0] == true)					//< PV1是坏点
		{
			if (Range_23 == Trans3_Normal)
				AO1_Out(PV2_Value, PV3_Value)				
			else
				AOSafe_Out
		}
		else if (AIfLink[0][0] == true && AIfLink[1][0] == false && AIfLink[2][0] == true)				//< PV2是坏点
		{
			if (Range_13 == Trans3_Normal)
				AO1_Out(PV1_Value, PV3_Value)
			else
				AOSafe_Out
		}
		else if (AIfLink[0][0] == true && AIfLink[1][0] == true && AIfLink[2][0] == false)				//< PV3是坏点
		{
			if (Range_12 == Trans3_Normal)
				AO1_Out(PV1_Value, PV2_Value)
			else
				AOSafe_Out
		}

		else if (AIfLink[0][0] == true && AIfLink[1][0] == true && AIfLink[2][0] == true)				//< 三个点均是好点
		{
			if ((Range_12 || Range_13 || Range_23) == Trans3_Normal)									//< 三路，两两之间都没有越限								
			{
				switch (Out_Mode)
				{
				case Trans3_Average: AO_Value = (PV1_Value + PV2_Value + PV3_Value) / 3; break;
				case Trans3_Max: AO_Value = tmp_in[2]; break;
				case Trans3_Min: AO_Value = tmp_in[0]; break;
				case Trans3_Middle: AO_Value = tmp_in[1]; break;
				}
				Alert_Sig = false;
				MRE = Trans3_Hold;
			}

			else if ((Range_12 == Trans3_Normal && Range_13 == Trans3_Normal && Range_23 == Trans3_Beyond)	//< 三路，两两之仅有一次越限
				|| (Range_12 == Trans3_Normal && Range_13 == Trans3_Beyond && Range_23 == Trans3_Normal)
				|| (Range_12 == Trans3_Beyond && Range_13 == Trans3_Normal && Range_23 == Trans3_Normal))
			{
				switch (Out_Mode)
				{
				case Trans3_Average: AO_Value = (PV1_Value + PV2_Value + PV3_Value) / 3; break;
				/*case Trans3_Max: AO_Value = (max(PV1_Value, PV2_Value)); AO_Value = (max(AO_Value, PV3_Value)); break;
				case Trans3_Min: AO_Value = (min(PV1_Value, PV2_Value)); AO_Value = (min(AO_Value, PV3_Value)); break;*/
				case Trans3_Max: AO_Value = tmp_in[2]; break;
				case Trans3_Min: AO_Value = tmp_in[0]; break;
				}
				Alert_Sig = true;
				MRE = Trans3_Hold;
			}
																												//< 三路，两两之间有两次越限
			else if (Range_12 == Trans3_Beyond && Range_13 == Trans3_Beyond && Range_23 == Trans3_Normal)		//< 1路与2路、3路均越限，但2、3未越限
				AOBeyond_Out(PV2_Value, PV3_Value)
			else if (Range_12 == Trans3_Beyond && Range_13 == Trans3_Normal && Range_23 == Trans3_Beyond)		//< 2路
				AOBeyond_Out(PV1_Value, PV3_Value)
			else if (Range_12 == Trans3_Normal && Range_13 == Trans3_Beyond && Range_23 == Trans3_Beyond)		//< 3路
				AOBeyond_Out(PV1_Value, PV2_Value)

			else if (Range_12 == Trans3_Beyond && Range_13 == Trans3_Beyond && Range_23 == Trans3_Beyond)		//< 两两都越限
			{
				AO_Value = Safe_OutValue;																		//< duan 按照文档编写，与明华不同																										
				Alert_Sig = true;
				MRE = Trans3_Change_MAN;

			}
		}

		else if (AIfLink[0][0] == false && AIfLink[1][0] == false && AIfLink[2][0] == true)						//< PV3是好点
				AO2_Out(PV3_Value)
		else if(AIfLink[0][0] == false && AIfLink[1][0] == true && AIfLink[2][0] == false)						//< PV2是好点
				AO2_Out(PV2_Value)
		else if (AIfLink[0][0] == true && AIfLink[1][0] == false && AIfLink[2][0] == false)						//< PV1是好点
				AO2_Out(PV1_Value)

		else
		{
			Alert_Sig = true;
			MRE = Trans3_Change_MAN;
		}
	}
	
	/*for (i = 0; i < Obj->Base.IO_Num.AI_Num; i++)
	{
		if (*(Obj->Base.In.AI_Pin_QualityInfo[i]) == true)
			Obj->Sta.AIfLink[i] = false;
	}*/

	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/
	
	/****************运算结果输出**************/
	AO[0] = AO_Value;
	DO[0] = Alert_Sig;
	DO[1] = MRE;
	
	/**************运算结果输出完毕************/
	return true;

#undef max
#undef min
#undef PV1_Work 
#undef PV2_Work 
#undef PV3_Work 
#undef AO1_Out
#undef AO2_Out
#undef AOSafe_Out
#undef AOBeyond_Out
}



//************************************
// Method:    	BCPARA						//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(Trans3)(Model_Base_t* arg, void** Data)
{
	
	NAME(Trans3)* Obj = (NAME(Trans3)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA						//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 指定模块类型链表的指针
// Parameter: 	void ** Data				//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(Trans3)(Model_Base_t* arg, void** Data)
{
	NAME(Trans3)* Obj = (NAME(Trans3)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA						//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int							//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(Trans3)(Model_Base_t* arg, void** Data)
{
	NAME(Trans3)* Obj = (NAME(Trans3)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(Trans3)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(Trans3)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR					//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/06/24
// Parameter: 	Model_Base_t* arg			//< 模块参数结构体指针
//************************************
void INIT_STAPAR(Trans3)(Model_Base_t* arg)
{
	int i;

	NAME(Trans3)* name = (NAME(Trans3)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/
	for (i = 0; i < name->Base.IO_Num.AI_Num; i++)
	{
		if (name->Base.In.AI_Pin_ID[i] > 0)
		{
			name->Sta.AIfLink[i] = true;
		}
	}
	/**************对中间变量结构体的相关参数进行赋值结束************/
}
